package simulaco.business;

import gminet.infra.business.BusinessException;
import gminet.infra.business.BusinessObject;
import gminet.infra.db.Transaction;
import gminet.infra.db.TransactionException;
import gminet.infra.toolkit.DateToolkit;
import gminet.infra.toolkit.NumberToolkit;
import gminet.infra.toolkit.StringToolkit;
import gminet.infra.toolkit.ValidatorToolkit;

import java.sql.Connection;
import java.util.Date;
import java.util.List;

import simulaco.dao.UsuarioDAO;
import simulaco.dto.Usuario;
import simulaco.dto.UsuarioMaster;
import simulaco.dto.UsuarioPerfil;
import simulaco.dto.UsuarioSituacao;

public class UsuarioBusiness extends BusinessObject {

    public static Usuario findByPK(int userId) throws TransactionException {

        Usuario user = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            user = UsuarioDAO.findByPK(userId, conn);
        } finally {
            transaction.release();
        }
        return user;
    }

    public static List<Usuario> findAll() throws TransactionException {

        List<Usuario> users = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            users = UsuarioDAO.findAll(conn);
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return users;
    }

    public static Usuario insert(Usuario usuario) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            //
            if (UsuarioDAO.existEmail(usuario.getEmail(), conn)) {
                throw new BusinessException("E-mail já cadastrado para outro usuário.");
            }
            // USUARIO
            Date dataAtual = DateToolkit.getDate();
            int rangeId = createRangeId(usuario.getNome());
            usuario.setCodigo(UsuarioDAO.getNextCodigo(conn, rangeId, rangeId + 1000));
            usuario.setSituacao(UsuarioSituacao.PENDENTE);
            usuario.setPerfil(UsuarioPerfil.USAURIO);
            usuario.setSenhaAcesso(LoginBusiness.crypt(usuario.getSenhaAcesso()));
            usuario.setDataCadastro(dataAtual);
            UsuarioDAO.insert(usuario, conn);
            // COMMIT
            transaction.commit();
            //
            return UsuarioDAO.findByPK(usuario.getCodigo(), conn);
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    private static int createRangeId(String usuarioName) {

        String strCodigo = "1";
        String caracter1 = usuarioName.substring(0, 1).toUpperCase();
        String caracter2 = usuarioName.substring(1, 2).toUpperCase();
        int valor1 = Math.abs(caracter1.compareTo("A") + 1);
        if (StringToolkit.isDigit(caracter1)) {
            valor1 = 0;
        }
        int valor2 = Math.abs(caracter2.compareTo("A") / 3);
        if (StringToolkit.isDigit(caracter2)) {
            valor2 = 0;
        }
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor1, 99), 2);
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor2, 9), 1);
        strCodigo += "000";
        return Integer.parseInt(strCodigo);
    }

    public static Usuario update(Usuario usuario) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            Usuario auxUsuario = UsuarioDAO.findByPK(usuario.getCodigo(), conn);
            usuario.setSituacao(auxUsuario.getSituacao());
            usuario.setPerfil(auxUsuario.getPerfil());
            usuario.setDataCadastro(auxUsuario.getDataCadastro());
            UsuarioDAO.update(usuario, conn);
            // COMMIT
            transaction.commit();
            //
            return UsuarioDAO.findByPK(usuario.getCodigo(), conn);
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void updateDados(Usuario user) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            UsuarioDAO.update(user, conn);
            if (StringToolkit.isFill(user.getSenhaAcesso())) {
                user.setSenhaAcesso(LoginBusiness.crypt(user.getSenhaAcesso()));
                UsuarioDAO.updatePassword(user, conn);
            }
            // COMMIT
            transaction.commit();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void updatePassword(Usuario usuario) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            usuario.setSenhaAcesso(LoginBusiness.crypt(usuario.getSenhaAcesso()));
            updatePassword(usuario, conn);
            // COMMIT
            transaction.commit();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void updatePassword(Usuario usuario, Connection conn) throws BusinessException, TransactionException {

        UsuarioDAO.updatePassword(usuario, conn);
    }

    public static void updateStatus(Usuario usuario) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            Usuario auxUsuario = UsuarioDAO.findByPK(usuario.getCodigo(), conn);
            auxUsuario.setSituacao(usuario.getSituacao());
            UsuarioDAO.update(auxUsuario, conn);
            // COMMIT
            transaction.commit();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void delete(Usuario usuario) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            UsuarioDAO.delete(usuario, conn);
            transaction.commit();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void verifyEmail(String email) throws TransactionException, BusinessException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            if (!StringToolkit.isFill(email) || !ValidatorToolkit.validateEmail(email)) {
                throw new BusinessException("Email inválido.", "email");
            }
            if (email.equalsIgnoreCase(UsuarioMaster.getInstance().getEmail())) {
                throw new BusinessException("Email já cadastrado.", "email");
            }
            if (UsuarioDAO.existEmail(email, conn)) {
                throw new BusinessException("Email já cadastrado por outro cliente.", "email");
            }
        } finally {
            transaction.release();
        }
    }

}
